package com.example.spring.controller;

import com.example.spring.constant.Constants;
import com.example.spring.pojo.AccessToken;
import com.example.spring.util.HttpClientUtil;
import com.example.spring.util.RedisUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


@RestController
public class WxController {
    private Logger logger = LoggerFactory.getLogger(WxController.class);
    private static final long MAX_TIME = 7000;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * wx获取access_token
     *
     * @return
     */
    @RequestMapping(value = "/get_access_token", method = RequestMethod.GET)
    public String getAssessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        String str = HttpClientUtil.sendGet(url, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
        JSONObject jsonObject = JSONObject.fromObject(str);
//        AccessToken accessToken = new AccessToken();
//
//        if (StringUtils.isNotBlank(String.valueOf(jsonObject))) {
//            accessToken.setToken(jsonObject.getString("access_token"));
//            accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
//        }
        return jsonObject.toString();
    }

    /**
     * wx获取ticket
     *
     * @return
     */
    @RequestMapping(value = "/get_ticket", method = RequestMethod.GET)
    public String getTicket() {
        String urlToken = "https://api.weixin.qq.com/cgi-bin/token";
        String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
        JSONObject jsonToken = JSONObject.fromObject(tokenObj);
        String access_token = jsonToken.getString("access_token");

        String urlTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
        String strTicket = HttpClientUtil.sendGet(urlTicket, "type=jsapi" + "&access_token=" + access_token);
        JSONObject jsonTicket = JSONObject.fromObject(strTicket);
        logger.info(jsonTicket.toString());
        return jsonTicket.toString();
    }

    /**
     * wx生成签名算法
     *
     * @return
     */
    @RequestMapping(value = "/get_signature", method = RequestMethod.GET)
    public Map<String, String> getSignature(String url) {
        Map<String, String> ret = new HashMap<String, String>();

        String wxTicket = getWxApiTicket();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String str;
        String signature = "";
        //注意这里参数名必须全部小写，且必须有序
        str = "jsapi_ticket=" + wxTicket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        logger.info(str);

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", wxTicket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appId", Constants.APPID);
        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    public String getWxAccessToken() {
        String urlToken = "https://api.weixin.qq.com/cgi-bin/token";
        String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
        JSONObject jsonToken = JSONObject.fromObject(tokenObj);
        String access_token = String.valueOf(jsonToken.get("access_token"));
        return access_token;
    }

    public String getWxTicket(String accessToken) {
        String urlTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
        String strTicket = HttpClientUtil.sendGet(urlTicket, "type=jsapi" + "&access_token=" + accessToken);
        JSONObject jsonTicket = JSONObject.fromObject(strTicket);
        return jsonTicket.getString("ticket");
    }

    public String getWxApiTicket() {
        String accessToken;
        String ticket;

        //全局缓存公众号accessToken和jsapi_ticket
        if (redisUtil.hasKey("wx_access_token")) {
            accessToken = String.valueOf(redisUtil.get("wx_access_token"));
        } else {
            accessToken = getWxAccessToken();
            redisUtil.set("wx_access_token", accessToken, MAX_TIME);
        }

        if (redisUtil.hasKey("wx_ticket")) {
            ticket = String.valueOf(redisUtil.get("wx_ticket"));
        } else {
            ticket = getWxTicket(accessToken);
            redisUtil.set("wx_ticket", ticket, MAX_TIME);
        }
        return ticket;
    }

    /**
     * 1.用户同意授权，获取code
     */
    @RequestMapping(value = "/get_code", method = RequestMethod.GET)
    public String getWxCode() throws UnsupportedEncodingException {
//        https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx615f42e4948c3009&redirect_uri=http%3A%2F%2F192.168.0.152%3A8080%2Fget_auth_access_token&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + Constants.APPID + "&redirect_uri="
                + URLEncoder.encode("http://192.168.0.152:8080/get_auth_access_token", "UTF-8") + "&response_type=code&scope="
                + Constants.GRANTSCOPE + "&state=STATE#wechat_redirect";
    }

    /**
     * 2.通过code换取网页授权access_token
     */
    @RequestMapping(value = "/get_auth_access_token", method = RequestMethod.GET)
    public void getAuthAccessToken(HttpServletRequest request, HttpServletResponse response, String code) throws IOException {
        String urlToken = "https://api.weixin.qq.com/sns/oauth2/access_token";
        String accessTokenObj = HttpClientUtil.sendGet(urlToken, "appid=" + Constants.APPID + "&secret="
                + Constants.APPSECRET + "&code=" + code + "&grant_type=authorization_code");
        JSONObject jsonToken = JSONObject.fromObject(accessTokenObj);

        String openId = null;
        String accessToken = null;
        if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {
            openId = jsonToken.getString("openid");
            accessToken = jsonToken.getString("access_token");
        }

        logger.info("openid={},access_token={}", openId, accessToken);
        //3.拉取用户信息(需scope为 snsapi_userinfo)
        String urlInfo = "https://api.weixin.qq.com/sns/userinfo";
        String infoObj = HttpClientUtil.sendGet(urlInfo, "access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN");
        JSONObject jsonUserInfo = JSONObject.fromObject(infoObj);
        if (StringUtils.isNotBlank(String.valueOf(jsonUserInfo))) {
            String nickName = jsonUserInfo.getString("nickname");
            String headImgUrl = jsonUserInfo.getString("headimgurl");
            String sex = jsonUserInfo.getString("sex");
            response.sendRedirect("http://lyx1314520ll.w3.luyouxia.net/auth?nickName=" + nickName + "&headImgUrl=" + headImgUrl + "&sex=" + sex);
        }
    }
}
